package se.lnu.axez.widgets;

import se.lnu.axez.AxezContext;
import se.lnu.axez.CompositeControl;
import se.lnu.axez.IControl;
import se.lnu.axez.Transformation;
import se.lnu.axez.animation.AccelerateDecelerateInterpolator;
import se.lnu.axez.animation.Animation;
import se.lnu.axez.animation.LinearInterpolator;
import android.util.FloatMath;
import android.view.MotionEvent;

public final class Carousel implements IControl {
	private static final float Z_DEVIATION = 0.15f;
	private static final float DIMENSION = 2f;
	private static final float WIDTH_SCALE = 1f;
	private static final float HEIGHT_SCALE = WIDTH_SCALE * 0.2f;
	private static final float DEPTH_SCALE = HEIGHT_SCALE * 0.5f;
	private static final float MARGIN = DIMENSION * 0.5f;
	private static final float STEP = DIMENSION + MARGIN;
	private final CompositeControl listWrapper = new CompositeControl();
	private float offset;
	private int itemsCount;
	private float radius = 5f;
	private final FloatAnimation floatAnimation;

	public Carousel() {
		this.floatAnimation = new FloatAnimation();
		addAnimation(this.floatAnimation);
	}

	public float getRadius() {
		return radius;
	}

	public void setRadius(float radius) {
		this.radius = Math.min(1f, radius);
	}

	@Override
	public Transformation getTransformation() {
		return this.listWrapper.getTransformation();
	}

	@Override
	public void init(AxezContext context) {
		this.listWrapper.init(context);
	}

	@Override
	public void draw(AxezContext context) {
		this.listWrapper.draw(context);
	}

	@Override
	public void addAnimation(Animation<IControl> animation) {
		this.listWrapper.addAnimation(animation);
	}

	public synchronized void addButton(IControl button) {
		this.listWrapper.addChild(button);
		this.itemsCount = this.listWrapper.getChildrenCount();
		this.floatAnimation.setDuration(this.itemsCount * FloatAnimation.DURATION_PER_ITEM);
		this.recalculateItemPositions();
	}

	@Override
	public void onTouchEvent(MotionEvent motionEvent) {
	}

	private void recalculateItemPositions() {
		int i = 0, count = this.listWrapper.getChildrenCount();
		float angleStep = (float) (2 * Math.PI / count);
		
		for (IControl button : this.listWrapper.getChildren()) {
			float angle = offset + angleStep * i++;
			float zPos = this.radius * FloatMath.sin(angle);
			float xPos = this.radius * FloatMath.cos(angle);
			button.getTransformation().setTranslation(xPos, 0f, zPos);
		}
	}
	
	private class FloatAnimation extends Animation<IControl> {
		private static final long DURATION_PER_ITEM = 3000L;
		
		public FloatAnimation() {
			setRepeatCount(REPEAT_COUNT_INFINITE);
			setRepeatMode(REPEAT_MODE_RESTART);
			setInterpolator(LinearInterpolator.newInstance());
		}
		
		@Override
		protected void applyTransformation(float interpolatedTime, IControl targetObject) {
			offset = (float) (16 * Math.PI / itemsCount * interpolatedTime);
			recalculateItemPositions();
		}
	}
}
